package com.chaofao.synchronization.common;

import cn.hutool.core.util.StrUtil;
import com.chaofao.synchronization.lang.TypeStateCode;
import com.chaofao.synchronization.model.FileInfo;
import com.chaofao.synchronization.model.Msg;
import com.chaofao.synchronization.web.SyncWebsocket;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.List;

/**
 * Created by Chaofan at 2018-11-12 10:52
 * email:chaofan2685@qq.com
 **/
public class ExistFileFilter implements FileFilter{

    //目的地文件夹的路径
    private String destDirectory;

    //允许复制的文件类型
    private List<String> fileTypes;

    //对比两个文件是否一致的算法（MD5/LENGTH）
    private String onlyArithmetic;

    //Websocket客户端
    private SyncWebsocket websocket;

    private List<FileInfo> fileInfos;


    public ExistFileFilter(String destDirectory, List<String> fileTypes, String onlyArithmetic,SyncWebsocket websocket,List<FileInfo> fileInfos) {
        this.destDirectory = destDirectory;
        this.fileTypes = fileTypes;
        this.onlyArithmetic = StrUtil.isNotEmpty(onlyArithmetic)?onlyArithmetic.toUpperCase():"NAME";
        this.websocket = websocket;
        this.fileInfos = fileInfos;
    }

    @Override
    public boolean accept(File pathname) {
        String name = pathname.getName();
        String newDir = destDirectory + "\\" + name;
        File newFile = new File(newDir);
        //先判断该文件是否是文件夹
        if (pathname.isDirectory()){
            if (!newFile.exists()){
                newFile.mkdir();
                websocket.sendMessage(Msg.build(TypeStateCode.MSGTYPE_FOLDER,TypeStateCode.MSGSTATE_BACKUP,pathname,"文件夹备份成功"));
            }
            try {
                FileUtils.copyDirectory(pathname,newFile,new ExistFileFilter(newDir,fileTypes,onlyArithmetic,websocket,fileInfos),true);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else {
            //是文件，则判断是否开启白名单
            if (fileTypes != null && fileTypes.size() != 0){
                //开启白名单，先判断该文件是否在白名单中
                for (String type : fileTypes){
                    if (name.toUpperCase().endsWith(type)){
                        //如果在白名单中，则对比源文件和目标文件是否相同
                        return contrast(pathname,newFile);
                    }
                }
                return false;
            }else {
                //未开启白名单，则直接对比源文件和目标文件是否相同
                return contrast(pathname,newFile);
            }
        }
        return false;
    }

    /**
     * 对比源文件和目标文件
     * @param pathname 源文件
     * @param newFile 目标文件
     * @return
     */
    private Boolean contrast(File pathname,File newFile){
        FileInfo info = new FileInfo(pathname,newFile,onlyArithmetic);
        //判断源文件是否在备份列表中
        if (!fileInfos.contains(info)){
            //如果不在，再判断他对应的文件是否在备份文件中
            FileInfo info2 = new FileInfo(newFile,pathname,onlyArithmetic);
            //先判断对应文件是否存在
            if (info2.getPath() == null){
                //对应文件不存在，则需要复制
                websocket.sendMessage(Msg.build(TypeStateCode.MSGTYPE_FILE,TypeStateCode.MSGSTATE_BACKUP,pathname,"备份成功"));
                return true;
            }else {
                //对应文件存在，判断对应文件的信息是否在fileInfos中
                if (!fileInfos.contains(info2)){
                    if (!new FileInfo(pathname,newFile,onlyArithmetic).equals(new FileInfo(newFile,pathname,onlyArithmetic))){
                        //如果对应文件也不在，说明两者版本冲突，都不变动,且需要记录下来
                        if (!SyncWebsocket.errorSyncList.containsKey(newFile.toString())){
                            String message = "备份失败：它与对应文件"+newFile.toString()+"内容有冲突，请手动删除其中一个！";
                            websocket.sendMessage(Msg.build(TypeStateCode.MSGTYPE_FILE,TypeStateCode.MSGSTATE_ERROR,pathname,message));
                            SyncWebsocket.errorSyncList.put(pathname.toString(),newFile.toString());
                        }
                    }
                    return false;
                }else {
                    //对应文件在，说明只有源文件发生变化，则需要复制
                    websocket.sendMessage(Msg.build(TypeStateCode.MSGTYPE_FILE,TypeStateCode.MSGSTATE_BACKUP,pathname,"备份成功"));
                    return true;
                }
            }
        }else {
            //如果在，说明没有变化，不复制
            return false;
        }
    }

}
